package com.halfsword.creativecraft.block.custom.machine.blockentity;

import com.halfsword.creativecraft.CreativeCraft;
import com.halfsword.creativecraft.block.custom.machine.blockentity.modules.*;
import com.halfsword.creativecraft.modules.interfaces.*;
import com.halfsword.creativecraft.utils.ContainerDataBuilder;
import com.halfsword.creativecraft.utils.ContainerDataReader;
import com.halfsword.creativecraft.utils.ContainerDataWriter;
import com.halfsword.creativecraft.utils.ModularContainerData;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.world.Containers;
import net.minecraft.world.MenuProvider;
import net.minecraft.world.SimpleContainer;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.ContainerData;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.ForgeCapabilities;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.items.IItemHandler;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.*;

/**
 * 机器方块实体的基础类，使用模块化设计
 * 1. 模块管理
 * 2. 配方处理流程
 * 3. 进度跟踪和数据同步
 */
public abstract class BaseMachineBlockEntity extends BlockEntity implements MenuProvider {

    // ================= 模块管理 =================
    protected final Map<String, IMachineModule> modules = new HashMap<>();
    protected final Map<Class<? extends IMachineModule>, List<IMachineModule>> modulesByFacet = new HashMap<>();

    // ================= 核心组件 =================
    protected final ModularContainerData containerData;
    protected final ContainerDataBuilder dataBuilder;
    protected LazyOptional<IItemHandler> lazyItemHandler = LazyOptional.empty();

    // ================= 状态变量 =================
    protected int progress = 0;
    protected int currentRecipeMaxProgress = 200;
    protected long lastRecipeCheckTime;

    // ================= 调试信息 =================
    private boolean debugEnabled = false;

    // ================= 构造函数 =================
    public BaseMachineBlockEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
        super(type, pos, state);
        this.dataBuilder = new ContainerDataBuilder();
        initializeModules();
        this.containerData = dataBuilder.build();

        // 添加基础数据字段
        setupBaseDataFields();

        // 记录调试信息
        if (debugEnabled) {
            CreativeCraft.LOGGER.debug("Built ModularContainerData with {} fields", containerData.getCount());
        }
    }

    // ================= 模块初始化 =================
    protected abstract void initializeModules();

    // ================= 基础数据字段设置 =================
    protected void setupBaseDataFields() {
        // 添加进度字段
        dataBuilder.addField(() -> progress, value -> {
            progress = value;
            setChanged();
        });

        // 添加最大进度字段
        dataBuilder.addField(() -> currentRecipeMaxProgress, value -> {
            currentRecipeMaxProgress = value;
            setChanged();
        });

        // 添加数据变化监听器
        dataBuilder.addChangeListener(this::setChanged);
    }

    // ================= 模块管理方法 =================
    protected void registerModule(IMachineModule module) {
        // 检查是否已存在相同ID的模块
        if (modules.containsKey(module.getModuleId())) {
            CreativeCraft.LOGGER.warn("Duplicate module ID: {}", module.getModuleId());
            return;
        }

        modules.put(module.getModuleId(), module);

        // 按接口类型分类
        for (Class<?> interfaceClass : module.getClass().getInterfaces()) {
            if (IMachineModule.class.isAssignableFrom(interfaceClass)) {
                Class<? extends IMachineModule> facetClass =
                        (Class<? extends IMachineModule>) interfaceClass;
                modulesByFacet.computeIfAbsent(facetClass, k -> new ArrayList<>()).add(module);
            }
        }

        // 如果是数据同步模块，添加其数据字段
        if (module instanceof IDataSyncFacet) {
            IDataSyncFacet syncModule = (IDataSyncFacet) module;
            if (debugEnabled) {
                CreativeCraft.LOGGER.debug("Adding data fields from module: {}", module.getModuleId());
            }
            syncModule.populateContainerData(dataBuilder);
        }

        // 调用模块的加载回调
        module.onLoad();
    }

    protected <T extends IMachineModule> Optional<T> getModule(String moduleId) {
        return Optional.ofNullable((T) modules.get(moduleId));
    }

    protected <T extends IMachineModule> List<T> getModules(Class<T> facetClass) {
        List<IMachineModule> modules = modulesByFacet.get(facetClass);
        if (modules == null) {
            return Collections.emptyList();
        }

        List<T> result = new ArrayList<>();
        for (IMachineModule module : modules) {
            if (facetClass.isInstance(module)) {
                result.add(facetClass.cast(module));
            }
        }
        return result;
    }

    // ================= 能力系统 =================
    public @NotNull <T> LazyOptional<T> getCapability(
            @NotNull Capability<T> cap,
            @Nullable Direction side
    ) {
        // 物品处理能力
        if (cap == ForgeCapabilities.ITEM_HANDLER) {
            List<IItemHandlerFacet> itemHandlers = getModules(IItemHandlerFacet.class);
            if (!itemHandlers.isEmpty()) {
                return LazyOptional.of(() -> itemHandlers.get(0).getItemHandler()).cast();
            }
        }

        // 流体处理能力
        if (cap == ForgeCapabilities.FLUID_HANDLER) {
            List<IFluidHandlerFacet> fluidHandlers = getModules(IFluidHandlerFacet.class);
            if (!fluidHandlers.isEmpty()) {
                return fluidHandlers.get(0).getFluidHandler().cast();
            }
        }

        return super.getCapability(cap, side);
    }

    // ================= 生命周期管理 =================
    @Override
    public void onLoad() {
        super.onLoad();

        // 初始化物品处理器的LazyOptional
        List<IItemHandlerFacet> itemHandlers = getModules(IItemHandlerFacet.class);
        if (!itemHandlers.isEmpty()) {
            lazyItemHandler = LazyOptional.of(() -> itemHandlers.get(0).getItemHandler());
        }

        // 调用所有模块的onLoad
        modules.values().forEach(IMachineModule::onLoad);
    }

    @Override
    public void invalidateCaps() {
        super.invalidateCaps();
        lazyItemHandler.invalidate();

        // 调用所有模块的onUnload
        modules.values().forEach(IMachineModule::onUnload);
    }

    // ================= 核心功能 =================
    public void tick(Level level, BlockPos pos, BlockState state) {
        if (level == null) return;

        // 服务器端逻辑
        if (!level.isClientSide()) {
            // 调用所有模块的tick方法
            modules.values().forEach(module -> {
                if (module.shouldExecuteOnServer()) {
                    module.tick(level, pos, state);
                }
            });

            // 处理配方逻辑
            handleRecipeProcessing(level);

            // 更新数据同步
            updateDataFromModules();
        } else {
            // 客户端逻辑
            modules.values().forEach(module -> {
                if (module.shouldExecuteOnClient()) {
                    module.tick(level, pos, state);
                }
            });

            // 客户端数据同步
            syncDataToModules();
        }
    }

    protected void handleRecipeProcessing(Level level) {
        // 定期检查配方（减少性能开销）
        if (level.getGameTime() - lastRecipeCheckTime > getRecipeCheckInterval()) {
            updateCurrentRecipe();
            lastRecipeCheckTime = level.getGameTime();
        }

        // 处理当前配方
        if (hasActiveRecipe()) {
            progress++;
            setChanged();

            if (progress >= currentRecipeMaxProgress) {
                createItems();
                progress = 0;
                setChanged();
            }
        } else {
            // 没有有效配方时重置状态
            resetProgress();
        }
    }

    // ================= 抽象方法（子类必须实现） =================
    protected abstract void updateCurrentRecipe();
    protected abstract boolean hasActiveRecipe();
    protected abstract void consumeInputs(int units);
    protected abstract ItemStack getMainOutputProduct();
    protected abstract ItemStack getByproductOutput();
    protected abstract void onRecipeChanged();

    // ================= 配方处理 =================
    protected void resetProgress() {
        if (progress > 0) {
            progress = 0;
            setChanged();
        }
    }

    protected int getRecipeCheckInterval() {
        return 20;
    }

    protected void createItems() {
        consumeInputs(1);  // 消耗1个单元的材料

        // 生成主产品
        distributeOutput(getMainOutputProduct().copy());

        // 生成副产品（如果有）
        if (shouldGenerateByproduct()) {
            distributeOutput(getByproductOutput().copy());
        }
    }

    protected boolean shouldGenerateByproduct() {
        return level != null && level.random.nextFloat() < getByproductChance();
    }

    protected float getByproductChance() {
        return 0.005F;
    }

    // ================= 数据同步 =================
    protected void updateDataFromModules() {
        // 从所有实现了IDataSyncFacet的模块收集数据
        ContainerDataReader reader = new ContainerDataReader(containerData);
        getModules(IDataSyncFacet.class).forEach(module -> {
            try {
                module.readFromContainerData(reader);
            } catch (IndexOutOfBoundsException e) {
                // 记录错误但不中断游戏
                CreativeCraft.LOGGER.error("Error reading data from module {}: {}", module.getModuleId(), e.getMessage());
            }
        });
    }

    protected void syncDataToModules() {
        // 将数据同步到所有实现了IDataSyncFacet的模块
        ContainerDataWriter writer = new ContainerDataWriter(containerData);
        getModules(IDataSyncFacet.class).forEach(module -> {
            try {
                // 注意：这里需要模块实现writeToContainerData方法
                if (module instanceof IDataSyncFacet.Extended) {
                    ((IDataSyncFacet.Extended) module).writeToContainerData(writer);
                }
            } catch (IndexOutOfBoundsException e) {
                CreativeCraft.LOGGER.error("Error writing data to module {}: {}", module.getModuleId(), e.getMessage());
            }
        });
    }

    // ================= 物品分发逻辑 =================
    protected void distributeOutput(ItemStack stack) {
        if (stack.isEmpty()) return;

        // 获取所有物品处理模块
        List<IItemHandlerFacet> itemHandlers = getModules(IItemHandlerFacet.class);

        // 尝试所有输出槽位
        for (IItemHandlerFacet handler : itemHandlers) {
            for (int slot : handler.getOutputSlots()) {
                if (handler.tryInsertItem(stack, slot)) {
                    return;
                }
            }
        }

        // 尝试部分插入
        smartStackDistribution(stack);
    }

    protected void smartStackDistribution(ItemStack stack) {
        int remaining = stack.getCount();

        // 获取所有物品处理模块
        List<IItemHandlerFacet> itemHandlers = getModules(IItemHandlerFacet.class);

        // 首先尝试部分堆叠
        for (IItemHandlerFacet handler : itemHandlers) {
            for (int slot : handler.getOutputSlots()) {
                ItemStack current = handler.getItemHandler().getStackInSlot(slot);

                if (!current.isEmpty() && ItemStack.isSameItemSameTags(current, stack)) {
                    int availableSpace = current.getMaxStackSize() - current.getCount();
                    if (availableSpace > 0) {
                        int toAdd = Math.min(availableSpace, remaining);
                        current.grow(toAdd);
                        remaining -= toAdd;

                        if (remaining <= 0) return;
                    }
                }
            }
        }

        // 尝试空槽位
        for (IItemHandlerFacet handler : itemHandlers) {
            for (int slot : handler.getOutputSlots()) {
                ItemStack current = handler.getItemHandler().getStackInSlot(slot);
                if (current.isEmpty()) {
                    ItemStack newStack = stack.copy();
                    newStack.setCount(Math.min(remaining, stack.getMaxStackSize()));
                    handler.getItemHandler().setStackInSlot(slot, newStack);
                    remaining -= newStack.getCount();

                    if (remaining <= 0) return;
                }
            }
        }

        // 处理剩余物品
        if (remaining > 0 && level != null) {
            handleOutputOverflow(stack, remaining);
        }
    }

    protected void handleOutputOverflow(ItemStack stack, int count) {
        ItemStack overflow = stack.copy();
        overflow.setCount(count);

        // 尝试存入玩家背包
        Player player = level.getNearestPlayer(
                worldPosition.getX(), worldPosition.getY(), worldPosition.getZ(),
                5, false
        );

        if (player != null && player.getInventory().add(overflow)) {
            return;
        }

        // 掉落物品
        Containers.dropItemStack(
                level,
                worldPosition.getX(), worldPosition.getY(), worldPosition.getZ(),
                overflow
        );

        // 播放警告音效
        if (level != null) {
            level.playSound(null, worldPosition,
                    getOverflowSound(), SoundSource.BLOCKS, 0.8f, 1.0f);
        }
    }

    protected SoundEvent getOverflowSound() {
        return SoundEvents.ITEM_BREAK;
    }

    // ================= 数据持久化 =================
    @Override
    protected void saveAdditional(CompoundTag tag) {
        super.saveAdditional(tag);

        // 保存模块数据
        CompoundTag modulesTag = new CompoundTag();
        modules.values().stream()
                .filter(module -> module instanceof IPersistentDataModule)
                .forEach(module -> {
                    IPersistentDataModule persistentModule = (IPersistentDataModule) module;
                    CompoundTag moduleTag = new CompoundTag();
                    persistentModule.saveToNBT(moduleTag);
                    modulesTag.put(persistentModule.getDataKey(), moduleTag);
                });
        tag.put("Modules", modulesTag);

        // 保存基础数据
        tag.putInt("progress", progress);
        tag.putInt("max_progress", currentRecipeMaxProgress);
        tag.putLong("last_check", lastRecipeCheckTime);
    }

    @Override
    public void load(CompoundTag tag) {
        super.load(tag);

        // 加载模块数据
        if (tag.contains("Modules")) {
            CompoundTag modulesTag = tag.getCompound("Modules");
            modules.values().stream()
                    .filter(module -> module instanceof IPersistentDataModule)
                    .forEach(module -> {
                        IPersistentDataModule persistentModule = (IPersistentDataModule) module;
                        String dataKey = persistentModule.getDataKey();
                        if (modulesTag.contains(dataKey)) {
                            persistentModule.loadFromNBT(modulesTag.getCompound(dataKey));
                        }
                    });
        }

        // 加载基础数据
        progress = tag.getInt("progress");
        currentRecipeMaxProgress = tag.getInt("max_progress");
        lastRecipeCheckTime = tag.getLong("last_check");
    }

    // ================= 清空机器内容物 =================
    public void drops() {
        if (level == null) return;

        // 获取所有物品处理模块
        List<IItemHandlerFacet> itemHandlers = getModules(IItemHandlerFacet.class);

        for (IItemHandlerFacet handler : itemHandlers) {
            SimpleContainer inventory = new SimpleContainer(handler.getItemHandler().getSlots());
            for (int i = 0; i < handler.getItemHandler().getSlots(); i++) {
                inventory.setItem(i, handler.getItemHandler().getStackInSlot(i));
            }
            Containers.dropContents(level, worldPosition, inventory);
        }
    }

    // ================= 公开方法（供GUI使用） =================
    public int getProgress() {
        return progress;
    }

    public int getMaxProgress() {
        return currentRecipeMaxProgress;
    }

    public boolean isProcessing() {
        return progress > 0;
    }

    public ContainerData getContainerData() {
        return containerData;
    }

    // ================= 调试方法 =================
    public void enableDebug(boolean enabled) {
        this.debugEnabled = enabled;
    }

    public int getDataFieldCount() {
        return containerData.getCount();
    }

    public String getModuleInfo() {
        StringBuilder sb = new StringBuilder();
        sb.append("Modules: ").append(modules.size()).append("\n");
        for (IMachineModule module : modules.values()) {
            sb.append("  - ").append(module.getModuleId());
            if (module instanceof IDataSyncFacet) {
                sb.append(" (Data fields: ").append(((IDataSyncFacet) module).getDataFieldCount()).append(")");
            }
            sb.append("\n");
        }
        return sb.toString();
    }
}